//
// Created by Pulsar on 2019/7/18.
//

#ifndef EASYMVM_CHIP8_H
#define EASYMVM_CHIP8_H

#include <QtWidgets>
#include <QtCore/QtCore>
#include <cstdint>
#include <cstdlib>
#include <stdio.h>
#include <cstring>
#include <ctime>
#include <modules/VMCore/include/base_vm_env/base_vm_env.hpp>

#define MEM_SIZE 4096
#define GFX_ROWS 32
#define GFX_COLS 64
#define GFX_SIZE (GFX_ROWS * GFX_COLS)
#define STACK_SIZE 16
#define KEY_SIZE 16

#define PIXEL_SIZE 5

#define CLOCK_HZ 60
#define CLOCK_RATE_MS ((int) ((1.0 / CLOCK_HZ) * 1000 + 0.5))

#define BLACK 0
#define WHITE 255

#define SCREEN_ROWS (GFX_ROWS * PIXEL_SIZE)
#define SCREEN_COLS (GFX_COLS * PIXEL_SIZE)

#define GFX_INDEX(row, col) ((row)*GFX_COLS + (col))

#define MAX_GAME_SIZE (0x1000 - 0x200)

class CHIP8 : public base_vm_env {

public:
    unsigned char screen[SCREEN_ROWS][SCREEN_COLS][3];
    unsigned short opcode;
    //TODO:0x000-0x1FF - Chip 8解释器(包含用于显示的字体)
    // 0x050-0x0A0 - 用于生成 4x5 像素的字体集合 (从’0’到’F’)
    // 0x200-0xFFF - 游戏ROM 与工作RAM
    uint8_t memory[MEM_SIZE];

    //TODO:CPU 寄存器：Chip 8 有16个单字节(1 byte)寄存器，
    // 名字为V0,V1...到VF. 前15个寄存器为通用寄存器，
    // 最后一个寄存器(VF)是个进位标志(carry flag)
    uint8_t V[16];
    //TODO: 索引寄存器I（Index register，暂译为“索引寄存器”）
    //  程序计数器PC（program counter），值域为0x000 到 0xFFF：
    uint16_t I;
    uint16_t PC;
    uint8_t gfx[GFX_ROWS][GFX_COLS];
    //TODO:计数器
    uint8_t delay_timer;
    uint8_t sound_timer;

    //TODO:堆栈
    uint16_t stack[STACK_SIZE];
    uint16_t SP;
    //TODO:按键
    uint8_t key[KEY_SIZE];


    int screen_rows = SCREEN_ROWS;
    int screen_cols = SCREEN_COLS;
    int clock_rate_ms = CLOCK_RATE_MS;
    int clock_hz = CLOCK_HZ;
    int pixel_size = PIXEL_SIZE;

    char *name = "CHIP8";

    bool draw_flag;

    void runCycle();

    void powerON();

    void powerOFF();

    void runAlways();

    void loadGame(char *file_path);

    void debug_screen();

    void setkeys(int index,int state);

    void tick();

    void draw_sprite(uint8_t x, uint8_t y, uint8_t n);


    void printState();


    void initialize();

    void print_cpu_info() ;
};


#endif //EASYMVM_CHIP8_H
